#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#define gettid() syscall(__NR_gettid)
  /* wrap the system call syscall(__NR_gettid), __NR_gettid = 224 */
#define gettidv2() syscall(SYS_gettid) /* a traditional wrapper */

#define STACK_SIZE 1024*1024 /* 1Mib. question: what is the upperbound of STACK_SIZE */



static int child_func1(void *arg)
{

    printf("child tpid %d\n", getpid());
    return 0;
}

void sighandler(int signum)
{
   printf("par signal\n");
   system("ps");
}



int main(int argc,char **argv)
{

    char *stack1 = malloc(STACK_SIZE*sizeof(char)); /* allocating from heap, safer than stack1[STACK_SIZE] */
    char *stack2 = malloc(STACK_SIZE*sizeof(char));
    pid_t chdtid1, chdtid2;
    unsigned long flags = 0;
    char buf[100]; /* a global variable has the same behavior */

    if(!stack1 || !stack2) {
        perror("malloc()");
        exit(1);
    }
    
      /* set CLONE flags */
    if((argc > 1) && (!strcmp(argv[1], "THREAD"))) {
        flags |= CLONE_THREAD;
    }
    if((argc > 2) && (!strcmp(argv[2], "vfork"))) {
        flags |= CLONE_VFORK;
    }

    sprintf(buf,"I am parent, my pid = %d", getpid());
    printf("parent set buf: %s\n", buf);
    sleep(1);
    printf("parrent clone ...\n");
    
    int fd = open("log/thread-1.log", O_RDONLY);

    int fd_flags;



    fd_flags = fcntl(fd, F_GETFL, 0);
    
    printf("parent fd_flags:%d\n", fd_flags);

    printf("par tpid %d\n", getpid());


      /* creat child thread, top of child stack is stack+STACK_SIZE */
    chdtid1 = clone(child_func1, stack1 + STACK_SIZE, flags | CLONE_SIGHAND |SIGCHLD  |CLONE_VM, &fd); /* what happened if without SIGCHLD */
    if(chdtid1 == -1) {
        perror("clone1()");
        exit(1);
    }

    // chdtid2 = clone(child_func2, stack2 + STACK_SIZE, flags | SIGCHLD, &fd);
    // if(chdtid2 == -1) {
    //     perror("clone2()");
    //     exit(1);
    // }

    
    printf("parent waiting ... \n");

    int status = 0;
    if(waitpid(-1, &status, 0) == -1) { /* wait for any child existing, may leave some child defunct */
        perror("wait()");
    }
  
//waitpid(chdtid1, &status, 0);
//waitpid(chdtid2, &status, 0);
  
    sleep(1);

    fd_flags = fcntl(fd, F_GETFL, 0);
    
    printf("parent fd_flags:%d\n", fd_flags);


    printf("parent read buf: %s\n", buf);

    system("ps");
    
    free(stack1);
    free(stack2);
    stack1 = NULL;
    stack2 = NULL;
    
    return 0;
}

